/**
* All Rights Reserved , Copyright (C) 2021 , 青岛鼎信通讯股份有限公司
*
* MpmProjectUniversalChangeService
* 项目变更通用
*
* 修改纪录
* 2021-08-18 版本：1.0 chengengwei 创建。
* @version 版本：1.0
* @author 作者：chengengwei
* 创建日期：2021-08-18
*/
package com.topscomm.mpm.service.impl;

import com.topscomm.basic.BasicEntity;
import com.topscomm.basic.util.PrimaryKeyUtil;
import com.topscomm.cbo.pojo.*;
import com.topscomm.cbo.service.ICboMessageAppService;
import com.topscomm.cbo.service.ICboMessageSysService;
import com.topscomm.mpm.pojo.*;
import com.topscomm.mpm.service.*;
import com.topscomm.mpm.service.impl.auto.MpmProjectUniversalChangeServiceAuto;
import com.topscomm.pub.util.ConvertUtil;
import com.topscomm.pub.util.StringBufferProxy;
import com.topscomm.pub.util.StringUtil;
import com.topscomm.tap.TapEntity;
import com.topscomm.tap.common.ParameterCache;
import com.topscomm.tap.common.SessionUserBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.topscomm.mpm.MpmSystemConst.*;

@Service(value = "mpmProjectUniversalChangeService")
@Scope(value = "singleton")
public class MpmProjectUniversalChangeService extends MpmProjectUniversalChangeServiceAuto implements IMpmProjectUniversalChangeService {

	@Autowired
	private IMpmProjectService mpmProjectService;

	@Autowired
    private ICboMessageAppService cboMessageAppService;

	@Autowired
    private ICboMessageSysService cboMessageSysService;

	@Autowired
    private IMpmProjectChangeService mpmProjectChangeService;

	@Autowired
    private IMpmProjectAppointmentService mpmProjectAppointmentService;

	@Autowired
    private IMpmProjectPlanService mpmProjectPlanService;

	/**
	 * @author: chengengwei
	 * @date: 2021-08-18
	 * @param entity
	 * @description:单号生成
	 * @modify:
	 */
	@Override
	protected void beforeInsert(BasicEntity entity) {
		super.beforeInsert(entity);
		if (entity.getId() <= 0) {// 赋值Id和单号
			long[] arrayId = PrimaryKeyUtil.GeneIDs(entity.getTableName(), 1);
			entity.setId(arrayId[0]);
			String docNo = String.valueOf(arrayId[0]);
			docNo = docNo.substring(0, 6) + docNo.substring(9);
			entity.setValue(MpmProjectUniversalChangeEntity.FieldDocno, docNo);
			MpmProjectUniversalChangeEntity changeEntity = (MpmProjectUniversalChangeEntity) entity;
			String changeCode = "BG";
			SimpleDateFormat sdFormat = new SimpleDateFormat("yyMMdd");
			String dateCode = sdFormat.format(new Date());
			String flowCode = docNo.substring(docNo.length() - 3);
			changeCode = changeCode + dateCode + flowCode;
			entity.setValue(changeEntity.FieldChangecode, changeCode);
		}
	}

	/**
	 * @author: chengengwei
	 * @date: 2021-08-19
	 * @description: 项目经理保存意见和审批人
	 * @modify:
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveApprovalUserAndOpinion(Map<String, Object> paraMap) {
		String id = ConvertUtil.convertToString(paraMap.get("applyid"));
		MpmProjectUniversalChangeEntity changeEntity = this.queryById(id);
		// 先将approvalusercodes和approvalusernames字段置空
		changeEntity.setAddapprovalusercodes("");
		changeEntity.setAddapprovalusernames("");
		// 保存审批人
		if (paraMap.containsKey("addapprovalusercodes") && !StringUtil.isEmpty(ConvertUtil
				.convertToString(paraMap.get("addapprovalusercodes")))) {
			this.setApprovalUser(changeEntity, paraMap);
		}
		// 保存项目经理意见
		this.setManagerOpinion(changeEntity, paraMap);
		this.updateEntity(changeEntity);
	}

	/**
	 * @author: chengengwei
	 * @date: 2021-08-19
	 * @description: 保存审批人
	 * @modify:
	 */
	private void setApprovalUser(MpmProjectUniversalChangeEntity changeEntity, Map<String, Object> paraMap) {
		String addapprovalusercodes = "," + ConvertUtil.convertToString(paraMap.get("addapprovalusercodes")) + ",";
		String addapprovalusernames = ConvertUtil.convertToString(paraMap.get("addapprovalusernames"));
		// 将变更记录的addapprovalusercodes、addapprovalusernames覆盖，更新allapprovalusercodes、allapprovalusernames
		String allapprovalusercodes = changeEntity.getAllapprovalusercodes();
		String allapprovalusernames = changeEntity.getAllapprovalusernames();
		// 如果oldallapprovalusercodes不为空则说明不是第一次选择审批人
		if (!StringUtil.isEmpty(allapprovalusercodes)) {
			String[] allCodesArr = allapprovalusercodes.split(",");
			String[] allNamesArr = allapprovalusernames.split(",");
			String[] addCodesArr = addapprovalusercodes.split(",");
			String[] addNamesArr = addapprovalusernames.split(",");
			// 将新增审批人加入到所有审批人前先去重
			allapprovalusercodes = "," + Stream.concat(Stream.of(allCodesArr), Stream.of(addCodesArr)
					.filter(item -> !StringUtil.isEmpty(item))).distinct().collect(Collectors.joining(",")) + ",";
			allapprovalusernames = Stream.concat(Stream.of(allNamesArr), Stream.of(addNamesArr)
					.filter(item -> !StringUtil.isEmpty(item))).distinct().collect(Collectors.joining(","));
		} else {
            allapprovalusercodes = addapprovalusercodes;
            allapprovalusernames = addapprovalusernames;
        }
		changeEntity.setAddapprovalusercodes(addapprovalusercodes);
		changeEntity.setAddapprovalusernames(addapprovalusernames);
		changeEntity.setAllapprovalusercodes(allapprovalusercodes);
		changeEntity.setAllapprovalusernames(allapprovalusernames);
	}

	/**
	 * @author: chengengwei
	 * @date: 2021-08-19
	 * @description: 保存项目经理意见
	 * @modify:
	 */
	private void setManagerOpinion(MpmProjectUniversalChangeEntity changeEntity, Map<String, Object> paraMap) {
		// 如果paraMap的KeySet包含opinion但Value为空则默认赋“同意”
		if (paraMap.containsKey("opinion")) {
			String opinion = ConvertUtil.convertToString(paraMap.get("opinion"));
			if (!StringUtil.isEmpty(opinion)) {
				changeEntity.setProjectmanageropinion(opinion);
			} else if (StringUtil.isEmpty(changeEntity.getProjectmanageropinion())) {
				changeEntity.setProjectmanageropinion("同意");
			}
		}
	}

	/**
	 * @author: chengengwei
	 * @date: 2021-08-20
	 * @description: 审批后保存意见
	 * @modify:
	 */
	@Override
	protected void afterApprove(TapEntity billEntity, CboApprovalNodeInsEntity nodeIns, CboApprovalNodeEntity node,
								 SessionUserBean sessionUserBean) {
		String selectNodeId = ParameterCache.getValue(SelectApprovalUserNodeId, "0");
		String comfirmNodeId = ParameterCache.getValue(StakeholderComfirmNodeId, "0");
		// 选择审批人节点
		if (selectNodeId.equals(ConvertUtil.convertToString(node.getId()))) {
			Map<String, Object> paraMap = new HashMap<>();
			paraMap.put("opinion", nodeIns.getApprovalopinion());
			this.setManagerOpinion((MpmProjectUniversalChangeEntity) billEntity, paraMap);
			this.updateEntity(billEntity);
		} else if (comfirmNodeId.equals(ConvertUtil.convertToString(node.getId()))) {// 相关方确认节点
			// 将新增审批人信息置为空
			((MpmProjectUniversalChangeEntity)billEntity).setAddapprovalusercodes("");
			((MpmProjectUniversalChangeEntity)billEntity).setAddapprovalusernames("");
			this.saveOpinion((MpmProjectUniversalChangeEntity) billEntity, nodeIns.getApprovalopinion());
		}
		super.afterApprove(billEntity, nodeIns, node, sessionUserBean);
	}

	/**
	 * @author: chengengwei
	 * @date: 2021-08-20
	 * @description: 保存除项目经理外其他人意见
	 * @modify:
	 */
	@Override
    @Transactional(rollbackFor = Exception.class)
	public void saveOpinion(MpmProjectUniversalChangeEntity changeEntity, String opinion) {
		// 查询项目信息
		List<MpmProjectEntity> mpmProjectEntities = this.mpmProjectService.queryByWhere(" projectcode = '"
				+ changeEntity.getProjectcode() + "' ");
		StringBuffer resultOpinion = new StringBuffer();
		if (!mpmProjectEntities.isEmpty()) {
			MpmProjectEntity mpmProjectEntity = mpmProjectEntities.get(0);
			// 当前用户code
			CboUserEntity user = getSessionUserBean().getUser();
			// 判断是否是owner
			if (user.getCode().equals(mpmProjectEntity.getOwnercode())) {
				// 已经保存过owner意见则换行
				if (!StringUtil.isEmpty(changeEntity.getOwneropinion())) {
					resultOpinion.append(changeEntity.getOwneropinion() + "\n");
				}
				// 意见为空默认赋值“同意”
				if (StringUtil.isEmpty(opinion)) {
					resultOpinion.append("同意");
				} else {
					resultOpinion.append(opinion);
				}
				changeEntity.setOwneropinion(resultOpinion.toString());
			} else {
				if (!StringUtil.isEmpty(changeEntity.getStakeholderopinion())) {
					resultOpinion.append(changeEntity.getStakeholderopinion() + "\n");
				}
				// 拼接当前用户信息
				resultOpinion.append(user.getName() + "【" + user.getCode() + "】：");
				// 意见为空默认赋值“同意”
				if (StringUtil.isEmpty(opinion)) {
					resultOpinion.append("同意");
				} else {
					resultOpinion.append(opinion);
				}
				changeEntity.setStakeholderopinion(resultOpinion.toString());
			}
		}
        this.updateEntity(changeEntity);
	}

    /**
     * @author: chengengwei
     * @date: 2021-08-20
     * @description: 保存除项目经理外其他人意见
     * @modify:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sendMessageToPMO(MpmProjectUniversalChangeEntity changeEntity) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("projectcode", changeEntity.getProjectcode());
        List<Map<String, Object>> queryPMOList = this.queryMap(paramMap, "queryPMO");
        if (!queryPMOList.isEmpty()) {
            CboUserEntity PMOEntity = new CboUserEntity();
            // 把结果集包装成CboUserEntity
            PMOEntity.convertFromMap(queryPMOList.get(0));
            // 消息内容
            String content = String.format(RemindPMOMessageContent, changeEntity.getProjectname());
            Map<String, Object> appMap = new HashMap<>();
			// 给PMO发送APP消息
            appMap.put(CboMessageAppEntity.FieldSourceid, changeEntity.getId());
            appMap.put(CboMessageAppEntity.FieldSourcetype, changeEntity.tableName);
            appMap.put("state", 0);
            appMap.put(CboMessageAppEntity.FieldSendcount, 0);
            appMap.put("usercode", PMOEntity.getCode());
            appMap.put(CboMessageAppEntity.FieldContent, content);
            appMap.put(CboMessageAppEntity.FieldExtendfield1, RemindPMOMessageSubject);
            this.cboMessageAppService.insertMap(appMap);
            // 给PMO发送系统提醒
			Map<String, Object> sysMap = new HashMap<>();
			sysMap.put(CboMessageSysEntity.FieldSourceid, changeEntity.getId());
			sysMap.put(CboMessageSysEntity.FieldSourcetype, changeEntity.tableName);
			sysMap.put(CboMessageSysEntity.FieldReceivercode, PMOEntity.getCode());
			sysMap.put(CboMessageSysEntity.FieldReceivername, PMOEntity.getName());
			sysMap.put("state", 0);
			sysMap.put(CboMessageSysEntity.FieldContent, content);
			sysMap.put(CboMessageSysEntity.FieldSubject, RemindPMOMessageSubject);
            this.cboMessageSysService.insertMap(sysMap);
        }
    }

	/**
	 * @author: chengengwei
	 * @date: 2021-08-23
	 * @description: 立项变更、项目任命、项目策划审批通过后调用该方法生成通用变更记录
	 * @modify:
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void createRecordAfterApproval(String sourcetype, String sourceid) {
		MpmProjectUniversalChangeEntity changeEntity = new MpmProjectUniversalChangeEntity();
		if (MpmProjectChangeEntity.tableName.equals(sourcetype)) {
			// 变更记录来源是立项变更
			this.createRecordByChange(changeEntity, sourceid);
		} else if (MpmProjectAppointmentEntity.tableName.equals(sourcetype)) {
			// 变更记录来源是项目任命，不是二次任命直接返回
			if (!this.createRecordByAppointment(changeEntity, sourceid)) {
				return;
			}
		} else if (MpmProjectPlanEntity.tableName.equals(sourcetype)) {
			// 变更记录来源是项目策划，不是二次策划直接返回
			if (!this.createRecordByPlan(changeEntity, sourceid)) {
				return;
			}
		}
		this.insert(changeEntity);
	}

	/**
	 * @author: chengengwei
	 * @date: 2021-08-23
	 * @description: 立项变更审批通过后生成通用变更记录
	 * @modify:
	 */
	private void createRecordByChange(MpmProjectUniversalChangeEntity changeEntity, String sourceid) {
		MpmProjectChangeEntity mpmProjectChangeEntity = this.mpmProjectChangeService.queryById(sourceid);
		changeEntity.setProjectcode(mpmProjectChangeEntity.getProjectcode2());
		changeEntity.setProjectmanager(mpmProjectChangeEntity.getProjectmanager2());
		changeEntity.setProjectmanagercode(mpmProjectChangeEntity.getProjectmanagercode2());
		changeEntity.setProjectname(mpmProjectChangeEntity.getProjectname2());
		changeEntity.setChangecontent(mpmProjectChangeEntity.getChangecontent());
		changeEntity.setLatestphase("结束");
		changeEntity.setState(9);
		changeEntity.setSubmitdate(mpmProjectChangeEntity.getSubmitdate());
		changeEntity.setSourcetype(mpmProjectChangeEntity.getTableName());
		changeEntity.setSourceid(mpmProjectChangeEntity.getId());
	}

	/**
	 * @author: chengengwei
	 * @date: 2021-08-23
	 * @description: 任命审批通过后生成通用变更记录
	 * @modify:
	 */
	private boolean createRecordByAppointment(MpmProjectUniversalChangeEntity changeEntity, String sourceid) {
		MpmProjectAppointmentEntity mpmProjectAppointmentEntity = mpmProjectAppointmentService.queryById(sourceid);
		changeEntity.setProjectcode(mpmProjectAppointmentEntity.getProjectcode());
		changeEntity.setProjectmanager(mpmProjectAppointmentEntity.getProjectmanager());
		changeEntity.setProjectmanagercode(mpmProjectAppointmentEntity.getProjectmanagercode());
		changeEntity.setProjectname(mpmProjectAppointmentEntity.getProjectname());
		changeEntity.setChangecontent(mpmProjectAppointmentEntity.getChangereason());
		changeEntity.setLatestphase("结束");
		changeEntity.setState(9);
		changeEntity.setSubmitdate(mpmProjectAppointmentEntity.getSubmitdate());
		changeEntity.setSourcetype(mpmProjectAppointmentEntity.getTableName());
		changeEntity.setSourceid(mpmProjectAppointmentEntity.getId());
		// 判断是否是二次任命，是二次任命返回true
		return !"1".equals(mpmProjectAppointmentEntity.getSyspush());
	}

	/**
	 * @author: chengengwei
	 * @date: 2021-08-23
	 * @description: 策划审批通过后生成通用变更记录
	 * @modify:
	 */
	private boolean createRecordByPlan(MpmProjectUniversalChangeEntity changeEntity, String sourceid) {
		MpmProjectPlanEntity mpmProjectPlanEntity = mpmProjectPlanService.queryById(sourceid);
		StringBufferProxy whereSql = new StringBufferProxy();
		whereSql.appendSingle(" {0} = '{1}' ", MpmProjectEntity.FieldProjectcode,
				mpmProjectPlanEntity.getProjectcode());
		List<MpmProjectEntity> mpmProjectEntities = mpmProjectService.queryByWhere(whereSql.toString());
		whereSql.clear();
		if (!mpmProjectEntities.isEmpty()) {
			changeEntity.setProjectmanager(mpmProjectEntities.get(0).getProjectmanager());
			changeEntity.setProjectmanagercode(mpmProjectEntities.get(0).getProjectmanagercode());
		}
		changeEntity.setProjectcode(mpmProjectPlanEntity.getProjectcode());
		changeEntity.setProjectname(mpmProjectPlanEntity.getProjectname());
		changeEntity.setChangecontent(mpmProjectPlanEntity.getChangereason());
		changeEntity.setLatestphase("结束");
		changeEntity.setState(9);
		changeEntity.setSubmitdate(mpmProjectPlanEntity.getSubmitdate());
		changeEntity.setSourcetype(mpmProjectPlanEntity.getTableName());
		changeEntity.setSourceid(mpmProjectPlanEntity.getId());
		whereSql.appendSingle(" {0} = '{1}' and state = '9' ", MpmProjectPlanEntity.FieldProjectcode,
				mpmProjectPlanEntity.getProjectcode());
		// 判断是否是二次策划
		return mpmProjectPlanService.getCount(whereSql.toString()) > 0;
	}

	/**
	 * @author: chengengwei
	 * @date: 2021-09-13
	 * @description: 获取上个版本单据的id
	 * @modify:
	 */
	@Override
	public void addLastVersionInfo(Map<String, Object> map) {
		StringBufferProxy sql = new StringBufferProxy();
		String sourcetype = ConvertUtil.convertToString(map.get(MpmProjectUniversalChangeEntity.FieldSourcetype));
		String projectcode = ConvertUtil.convertToString(map.get("projectcode"));
		if (!ChangeSourceTypeEnum.UniversalChange.equals(sourcetype)) {
			Map<String, Object> paramsMap = new HashMap<>();
			paramsMap.put("sourcetype", sourcetype);
			paramsMap.put("projectcode", projectcode);
			paramsMap.put("sourceid", ConvertUtil.convertToString(map.get("sourceid")));
			if (ChangeSourceTypeEnum.Change.equals(sourcetype)) {
				paramsMap.put("projectcodefield", "projectcode2");
			} else {
				paramsMap.put("projectcodefield", "projectcode");
			}
			// 查询同一个项目中当前单据的上一个记录
			List<Map<String, Object>> idList = this.queryMap(paramsMap, "queryLastRecordId");
			// 若idList为空且类型为立项变更，则说明为初次立项变更，通过projectcode和firstvisionflag获取符合条件的记录
			if (ChangeSourceTypeEnum.Change.equals(sourcetype) && idList.isEmpty()) {
				sql.clear();
				sql.appendSingle(" projectcode2 = '{0}' and {1} = '1' ", projectcode,
						MpmProjectChangeEntity.FieldFirstvisionflag);
				idList = this.mpmProjectChangeService.queryMapByWhere(sql.toString());
			}
			if (!idList.isEmpty()) {
				map.put("lastsourceid", idList.get(0).get("id"));
			}
		}
	}
}
